// 安全内存管理服务 - 仅使用safe Rust

use std::sync::Mutex;
use log::{info, warn, error};

use super::{Capability, PhysicalAddress, VirtualAddress, MemoryPermissions};
use super::exokernel_allocate_physical_memory;
use super::exokernel_free_physical_memory;
use super::exokernel_map_memory;
use super::exokernel_unmap_memory;

// 物理内存块
pub struct PhysicalMemoryBlock {
    address: PhysicalAddress,
    size: u64,
    used: bool,
}

// 虚拟内存块
pub struct VirtualMemoryBlock {
    virt_address: VirtualAddress,
    phys_address: PhysicalAddress,
    size: u64,
    perms: MemoryPermissions,
    used: bool,
}

// 内存管理服务
pub struct MemoryService {
    memory_cap: Capability,
    physical_blocks: Vec<Mutex<PhysicalMemoryBlock>>,
    virtual_blocks: Vec<Mutex<VirtualMemoryBlock>>,
    initialized: bool,
}

impl MemoryService {
    // 创建新的内存服务
    pub fn new(memory_cap: Capability) -> Result<Self, String> {
        if !memory_cap.is_acquired() {
            return Err("Memory capability not acquired".to_string());
        }

        Ok(MemoryService {
            memory_cap,
            physical_blocks: Vec::new(),
            virtual_blocks: Vec::new(),
            initialized: false,
        })
    }

    // 启动内存服务
    pub fn start(&mut self) -> Result<(), String> {
        info!("Starting memory service");
        // 初始化内存服务
        self.initialized = true;
        info!("Memory service started successfully");
        Ok(())
    }

    // 分配物理内存
    pub fn allocate_physical_memory(&mut self, size: u64, alignment: u64) -> Result<PhysicalAddress, String> {
        if !self.initialized {
            return Err("Memory service not initialized".to_string());
        }

        let cap_id = self.memory_cap.id();
        let address = unsafe {
            exokernel_allocate_physical_memory(cap_id, size, alignment)
        };

        if address == 0 {
            return Err("Failed to allocate physical memory".to_string());
        }

        // 记录分配的内存块
        let block = PhysicalMemoryBlock {
            address,
            size,
            used: true,
        };
        self.physical_blocks.push(Mutex::new(block));

        info!("Allocated {} bytes of physical memory at address 0x{:x}", 
              size, address);
        Ok(address)
    }

    // 释放物理内存
    pub fn free_physical_memory(&mut self, address: PhysicalAddress, size: u64) -> Result<bool, String> {
        if !self.initialized {
            return Err("Memory service not initialized".to_string());
        }

        // 查找内存块
        let block_index = match self.physical_blocks.iter().position(|block| {
            let b = block.lock().unwrap();
            b.address == address && b.size == size && b.used
        }) {
            Some(idx) => idx,
            None => return Err("Memory block not found or already freed".to_string()),
        };

        // 释放内存
        let cap_id = self.memory_cap.id();
        let result = unsafe {
            exokernel_free_physical_memory(cap_id, address, size)
        };

        if result {
            // 更新内存块状态
            {{
                let mut block = self.physical_blocks[block_index].lock().unwrap();
                block.used = false;
            }}
            info!("Freed {} bytes of physical memory at address 0x{:x}", 
                  size, address);
        } else {
            warn!("Failed to free physical memory at address 0x{:x}", address);
        }

        Ok(result)
    }

    // 映射内存
    pub fn map_memory(
        &mut self,
        virt_addr: VirtualAddress,
        phys_addr: PhysicalAddress,
        size: u64,
        perms: MemoryPermissions,
    ) -> Result<bool, String> {
        if !self.initialized {
            return Err("Memory service not initialized".to_string());
        }

        // 检查物理内存块是否存在
        let exists = self.physical_blocks.iter().any(|block| {
            let b = block.lock().unwrap();
            b.address == phys_addr && b.size >= size && b.used
        });

        if !exists {
            return Err("Invalid physical memory address or size".to_string());
        }

        // 执行映射
        let cap_id = self.memory_cap.id();
        let result = unsafe {
            exokernel_map_memory(cap_id, virt_addr, phys_addr, size, perms)
        };

        if result {
            // 记录映射
            let block = VirtualMemoryBlock {
                virt_address: virt_addr,
                phys_address: phys_addr,
                size,
                perms,
                used: true,
            };
            self.virtual_blocks.push(Mutex::new(block));
            info!("Mapped {} bytes from physical address 0x{:x} to virtual address 0x{:x}", 
                  size, phys_addr, virt_addr);
        } else {
            warn!("Failed to map memory from 0x{:x} to 0x{:x}", phys_addr, virt_addr);
        }

        Ok(result)
    }

    // 解除映射
    pub fn unmap_memory(
        &mut self,
        virt_addr: VirtualAddress,
        size: u64,
    ) -> Result<bool, String> {
        if !self.initialized {
            return Err("Memory service not initialized".to_string());
        }

        // 查找映射
        let block_index = match self.virtual_blocks.iter().position(|block| {
            let b = block.lock().unwrap();
            b.virt_address == virt_addr && b.size == size && b.used
        }) {
            Some(idx) => idx,
            None => return Err("Virtual memory block not found or already unmapped".to_string()),
        };

        // 解除映射
        let cap_id = self.memory_cap.id();
        let result = unsafe {
            exokernel_unmap_memory(cap_id, virt_addr, size)
        };

        if result {
            // 更新映射状态
            {{
                let mut block = self.virtual_blocks[block_index].lock().unwrap();
                block.used = false;
            }}
            info!("Unmapped {} bytes of virtual memory at address 0x{:x}", 
                  size, virt_addr);
        } else {
            warn!("Failed to unmap virtual memory at address 0x{:x}", virt_addr);
        }

        Ok(result)
    }

    // 创建内存权限
    pub fn create_permissions(read: bool, write: bool, execute: bool) -> MemoryPermissions {
        MemoryPermissions {
            read,
            write,
            execute,
            _reserved: 0,
        }
    }
}